/* 
 *  Copyright 2012 CodeMagi, Inc.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.codemagi.taglibs.taxonomy;

import com.codemagi.servlets.model.*;
import com.codemagi.util.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.*;

/**
 * This class implements the &lt;tax:checkboxes&gt; tag, which presents a set of checkboxes to choose multiple taxonomy terms
 *
 *  @version 1.0
 *  @author August Detlefsen for CodeMagi, Inc.
 */
public class TaxonomyCheckboxes extends TaxonomyTag {

    private String altValue = "";  //alternate to use for value instead of name
    private boolean filter = false;  //if true, only show terms w/ non-null sortOrder

    public void setAltValue(String newValue) {
        altValue = newValue;
    }

    public void setFilter(boolean x) {
        filter = x;
    }

    public int doStartTag() throws JspException {

	// sanity check
	if (categoryId == null) throw new JspTagException("invalid categoryId specified");

  	//determine the name for the select list
	String name = "taxonomy_" + categoryId;

        try {
            // get what we need from the page
            ServletRequest req = pageContext.getRequest();
            JspWriter out = pageContext.getOut();

            // start building up the tag
            out.println();
            out.println("<div ");
            out.println("    name=\"" + name + "\"");
            if (!Utils.isEmpty(id)) {
                out.println("    id=\"" + quote(id) + "\"");
            }

            //if this is a required field and it is not filled out, do something...
            if ( !Utils.isEmpty((String)req.getAttribute("error_" + name + "_error")) ) {
                out.println("    class=\"" + markupClass + "_error\"");
            } else if ( !Utils.isEmpty(markupClass) ) {
                out.println("    class=\"" + markupClass + "\"");
            }

            // end the starting tag
            out.println(">");


            /*
             * Print out our options, selecting one or more if appropriate.
             */

            // get the current selection.
	    String[] selected = getParameterValues(name, (HttpServletRequest)req);
            log.debug("Select: selected: " + selected);
            log.debug("Select: (selected != null) = " + (selected != null));
            log.debug("Select: (selected != null && selected.length > 1) = " + (selected != null && selected.length > 1));
            log.debug("Select: (attributes == null) + " + (attributes == null));

            // load up the selected values into a hash table for faster access
            // otherwise use defaults
            HashMap chosen = new HashMap();

            if (selected == null || override) {
                log.debug("Select: building chosen from Node");

                List selectedTerms = (node == null) ? new ArrayList<Term>() : node.getTerms(categoryId) ;

                Iterator e = selectedTerms.iterator();
                while (e.hasNext()) {
		    Term term = (Term)e.next();

                    chosen.put(term.getId() + "", null);
                }
            } else {
                log.debug("Select: building chosen from request");

                for (int i = 0; i < selected.length; i++) {
                    chosen.put(selected[i], null);
                }

            }

	    log.debug("CHOSEN: " + CollectionUtils.commaDelimit(chosen.keySet()) );

            // actually print the <checkbox> tags
	    List options = category.getTerms();

	    if (sort) {
		//sort options by natural order
		Collections.sort(options);
	    }

	    Iterator i   = options.iterator();

	    while (i.hasNext()) {
		Term term = (Term)i.next();
		
		if (filter && term.getSortOrder() == null) continue;

		String key        = term.getId() + "";
		String value      = term.getName();
		String checkboxId = name + "_" + key;

		if (key == null) continue;  //do not allow null keys

		//Check if alternate value is desired
		if ("alias".equals(altValue))
		    value = term.getAlias();
		else if ("shortName".equals(altValue))
		    value = term.getShortName();
		else if ("description".equals(altValue))
		    value = term.getDescription();

		if (value == null) value = key;     // use key if value is null

		out.print("<div class=\"taxonomy_checkbox\">");
		out.print("<input type=\"checkbox\" name=\"" + name + "\" value=\"" + key + "\" id=\"" + checkboxId + "\"");

		//determine if this option should be selected
		if ( chosen.containsKey(key) ) out.print(" checked=\"checked\"");

		//disable the form field if disabled is set
		if (disabled) {
		    out.println("    readonly=\"readonly\"");
		    out.println("    OnFocus=\"blur();\"");
		    appendAttribute("style", "cursor:default;");
		}
		
		// include any attributes we've got here
		printAttributes(out, attributes);

		out.print("/>");
		out.print("<label for=\"" + checkboxId + "\"");

		//does this term have a toolitip associated? 
		boolean doTooltip = showTooltips && !Utils.isEmpty(term.getToolTip());
		if (doTooltip) {
		    out.print(" class=\"popper\" title=\"" + quote(term.getToolTip()) + "\"");
		}
		out.print(">" + quote(value));

		if (doTooltip && !Utils.isEmpty(tooltipImage)) out.print("<img class=\"tooltipImage\" src=\"" + tooltipImage + "\"/>");

		out.println("</label></div>");
	    }

	    //Add a hidden field with no value so TaxonomyController.setTerms() will recognize that 
	    //this category is present even if no boxes are checked
	    out.print("<input type=\"hidden\" name=\"" + name + "\" value=\"\" />");

            // close off the surrounding div
            out.println("</div>");

        } catch (Exception ex) {
            log.debug("", ex);
            throw new JspTagException(ex.getMessage());
        }
        return SKIP_BODY;
    }

}
